package com.advertisementsystem.Controller;

import com.advertisementsystem.Dto.DeviceDTO;
import com.advertisementsystem.Dto.LoginUser;
import com.advertisementsystem.Mapper.DeviceMapper;
import com.advertisementsystem.Servie.DeviceService;
import com.advertisementsystem.Servie.DeviceStatisticsService;
import com.advertisementsystem.Servie.StatisticsService;
import com.advertisementsystem.entity.Device;
import com.advertisementsystem.Exception.ResponseResult;
import com.advertisementsystem.vo.DeviceStatisticsExportVO;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/device")
@Slf4j
public class DeviceController {

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private DeviceStatisticsService deviceStatisticsService;

    @Autowired
    private StatisticsService statisticsService;

    // 创建设备 11
    @PostMapping
    @PreAuthorize("hasAuthority('device:create')")
    public ResponseResult<?> createDevice(@RequestBody @Valid DeviceDTO dto) {
        deviceService.createDevice(dto);
        return ResponseResult.success("");
    }

    // 更新设备 11
    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('device:update')")
    public ResponseResult<?> updateDevice(
            @PathVariable Long id,
            @RequestBody @Valid DeviceDTO dto) {
        deviceService.updateDevice(id, dto);
        return ResponseResult.success("");
    }

    // 删除设备 11
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('device:delete')")
    public ResponseResult<?> deleteDevice(@PathVariable Long id) {
        deviceService.deleteDevice(id);
        return ResponseResult.success("");
    }

    // 获取设备列表 11
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('device:list')")
    public ResponseResult<Page<Device>> getDeviceList(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            String name,
            Integer status,
            String keyword,
            String type) {
        log.info("获取设备列表 - pageNum: {}, pageSize: {}, name: {}, status: {}", pageNum, pageSize, name, status);
        return ResponseResult.success(deviceService.getDeviceList(pageNum, pageSize,name,status,keyword,type));
    }

    // 获取设备详情 11
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('device:list')")
    public ResponseResult<Device> getDeviceDetail(@PathVariable Long id) {
        return ResponseResult.success(deviceService.getDeviceDetail(id));
    }

    // 启用设备 11
    @PutMapping("/{id}/enable")
    @PreAuthorize("hasAuthority('device:update')")
    public ResponseResult<?> enableDevice(@PathVariable Long id) {
        deviceService.enableDevice(id);
        return ResponseResult.success("");
    }

    // 禁用设备 11
    @PutMapping("/{id}/disable")
    @PreAuthorize("hasAuthority('device:update')")
    public ResponseResult<?> disableDevice(@PathVariable Long id) {
        deviceService.disableDevice(id);
        return ResponseResult.success("");
    }

    @GetMapping("/stats")
    public ResponseResult<Map<String, Object>> getDeviceStats() {
        try {
            Long ownerId = getCurrentUserId();
            log.info("获取设备统计数据 - ownerId: {}", ownerId);

            // 获取总设备数
            LambdaQueryWrapper<Device> totalQuery = new LambdaQueryWrapper<>();
            totalQuery.eq(Device::getOwnerId, ownerId);
            int total = Math.toIntExact(deviceMapper.selectCount(totalQuery));

            // 获取启用设备数
            LambdaQueryWrapper<Device> activeQuery = new LambdaQueryWrapper<>();
            activeQuery.eq(Device::getOwnerId, ownerId)
                    .eq(Device::getStatus, 1);
            int active = Math.toIntExact(deviceMapper.selectCount(activeQuery));

            // 获取禁用设备数
            LambdaQueryWrapper<Device> disabledQuery = new LambdaQueryWrapper<>();
            disabledQuery.eq(Device::getOwnerId, ownerId)
                    .eq(Device::getStatus, 0);
            int disabled = Math.toIntExact(deviceMapper.selectCount(disabledQuery));

            // 返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("total", total);
            result.put("active", active);
            result.put("disabled", disabled);

            return ResponseResult.success(result);
        } catch (Exception e) {
            log.error("获取设备统计数据失败", e);
            return ResponseResult.error("获取设备统计数据失败：" + e.getMessage());
        }
    }
    /**
     * 获取当前登录用户ID
     */
    private Long getCurrentUserId() {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();
        return loginUser.getUser().getId();
    }



    /**
     * 获取设备统计数据
     */
    @GetMapping("/{deviceId}/statistics")
    @PreAuthorize("hasAnyAuthority('device:list')")
    public ResponseResult<Map<String, Object>> getDeviceStatistics(
            @PathVariable Long deviceId) {
        try {
            return ResponseResult.success(deviceStatisticsService.getDeviceStatistics(deviceId));
        } catch (Exception e) {
            log.error("获取设备统计数据失败", e);
            return ResponseResult.error("获取设备统计数据失败：" + e.getMessage());
        }
    }

    /**
     * 获取设备收入统计
     */
    @GetMapping("/{deviceId}/income-stats")
    @PreAuthorize("hasAnyAuthority('device:list')")
    public ResponseResult<Map<String, Object>> getDeviceIncomeStats(
            @PathVariable Long deviceId) {
        try {
            return ResponseResult.success(deviceStatisticsService.getDeviceIncomeStats(deviceId));
        } catch (Exception e) {
            log.error("获取设备收入统计失败", e);
            return ResponseResult.error("获取设备收入统计失败：" + e.getMessage());
        }
    }
    /**
     * 获取设备最近7天的收入
     */
    @GetMapping("/{deviceId}/weekly-income")
    @PreAuthorize("hasAnyAuthority('device:list')")
    public ResponseResult<List<Map<String, Object>>> getDeviceWeeklyIncome(
            @PathVariable Long deviceId) {
        try {
            return ResponseResult.success(deviceStatisticsService.getDeviceWeeklyIncome(deviceId));
        } catch (Exception e) {
            log.error("获取设备最近7天的收入失败", e);
            return ResponseResult.error("获取设备最近7天的收入失败：" + e.getMessage());
        }
    }

    /**
     * 获取设备广告排期
     */
    @GetMapping("/{deviceId}/ad-schedules")
    @PreAuthorize("hasAnyAuthority('device:list')")
    public ResponseResult<Map<String, Object>> getDeviceAdSchedules(
            @PathVariable Long deviceId,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        try {
            return ResponseResult.success(deviceStatisticsService.getDeviceAdSchedules(deviceId, pageNum, pageSize));
        } catch (Exception e) {
            log.error("获取设备广告排期失败", e);
            return ResponseResult.error("获取设备广告排期失败：" + e.getMessage());
        }
    }

    @GetMapping("/{deviceId}/export")
    @PreAuthorize("hasAnyRole('ADMIN', 'DEVICE_OWNER')")
    public void exportDeviceStatistics(
            @PathVariable Long deviceId,
            HttpServletResponse response) {
        try {
            // 设置响应头
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("设备统计数据", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

            // 获取统计数据
            Map<String, Object> statistics = statisticsService.getDeviceStatistics(deviceId);

            // 准备数据
            List<Map<String, Object>> adStats = (List<Map<String, Object>>) statistics.get("adStats");
            List<DeviceStatisticsExportVO> exportData = adStats.stream().map(stat -> {
                DeviceStatisticsExportVO vo = new DeviceStatisticsExportVO();
                vo.setAdTitle((String) stat.get("ad_title"));
                vo.setAdvertiserName((String) stat.get("advertiser_name"));
                vo.setPlayCount((Integer) stat.get("play_count"));
                vo.setViewCount((Integer) stat.get("view_count"));
                vo.setViewRate(calculateViewRate((Integer) stat.get("play_count"),
                        (Integer) stat.get("view_count")));
                return vo;
            }).collect(Collectors.toList());

            // 导出数据
            EasyExcel.write(response.getOutputStream(), DeviceStatisticsExportVO.class)
                    .sheet("设备统计")
                    .doWrite(exportData);

        } catch (Exception e) {
            log.error("导出设备统计数据失败", e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
    }
    // 计算观看率
    private String calculateViewRate(Integer playCount, Integer viewCount) {
        if (playCount == null || playCount == 0) {
            return "0%";
        }
        double rate = (double) viewCount / playCount * 100;
        return String.format("%.2f%%", rate);
    }


    @GetMapping("/map")
    public ResponseResult<List<Device>> getDevicesForMap(
            @RequestParam(required = false) BigDecimal minLng,
            @RequestParam(required = false) BigDecimal minLat,
            @RequestParam(required = false) BigDecimal maxLng,
            @RequestParam(required = false) BigDecimal maxLat) {

        QueryWrapper<Device> query = new QueryWrapper<>();
        if (minLng != null && minLat != null && maxLng != null && maxLat != null) {
            query.between("longitude", minLng, maxLng)
                    .between("latitude", minLat, maxLat);
        }
        return ResponseResult.success(deviceMapper.selectList(query));
    }
}